package shop.ynubeggar.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import shop.ynubeggar.constant.RedisCacheKey;
import shop.ynubeggar.exception.CustomException;
import shop.ynubeggar.interceptor.LoginInterceptor;
import shop.ynubeggar.model.valueobject.CartItemVO;
import shop.ynubeggar.model.valueobject.CartVO;
import shop.ynubeggar.model.valueobject.LoginUser;
import shop.ynubeggar.model.valueobject.ProductVO;
import shop.ynubeggar.request.CartItemRequest;
import shop.ynubeggar.service.CartService;
import shop.ynubeggar.service.ProductService;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CartServiceImpl implements CartService {

    @Resource
    RedisTemplate redisTemplate;

    @Resource
    ProductService productService;

    @Override
    public void addToCart(CartItemRequest cartItemRequest) {
        long productId = cartItemRequest.getId();

        int buyNum = cartItemRequest.getNum();

        // NOTES 获取购物车：Map<id,cartItemVO>，redis存对象，要将对象先序列化为json再存
        BoundHashOperations<String, Long, String> myCart = getCart();
        // 有没有一种可能：购物车不存在。 /->不存在则创建。

        if (Boolean.TRUE.equals(myCart.hasKey(productId))) {
//            商品存在
            CartItemVO cartItemVO = JSONUtil.toBean(myCart.get(productId), CartItemVO.class);
            cartItemVO.setBuyNum(cartItemVO.getBuyNum() + buyNum);
            myCart.put(productId, JSONUtil.toJsonStr(cartItemVO));
        } else {
//            不存在
            CartItemVO cartItemVO = new CartItemVO();
            ProductVO productVO = productService.findDetail(productId);
            BeanUtil.copyProperties(productVO, cartItemVO);
            cartItemVO.setBuyNum(buyNum);
            cartItemVO.getTotalPrice();
            myCart.put(productId, JSONUtil.toJsonStr(cartItemVO));
        }
    }

    @Override
    public void delAllCartItems() {
        String cartKey = produceCartKey();
        redisTemplate.delete(cartKey);
    }

    @Override
    public CartVO viewCart() {
        String cartKey = produceCartKey();
        List<CartItemVO> cartItemVOList = getCart().values().stream().map(obj -> JSONUtil.toBean(obj, CartItemVO.class)).collect(Collectors.toList());
        if (cartItemVOList.isEmpty()){
            throw new CustomException(HttpStatus.NOT_FOUND, "cart has no goods");
        }
        // 获取所有商品id以供查询最新价格；
        List<Long> productIdList = cartItemVOList.stream().map(CartItemVO::getId).collect(Collectors.toList());

        // 查询商品最新信息
        Map<Long, ProductVO> latestProductInfo = findLatestPrice(productIdList);

        // 修改信息
        cartItemVOList = cartItemVOList.stream().map(obj -> {
            obj.setPrice(latestProductInfo.get(obj.getId()).getPrice());
            return obj;
        }).collect(Collectors.toList());

//        NOTES 这里的构造函数有讲究
        CartVO cartVO = new CartVO(cartItemVOList);
        if (Objects.equals(cartVO.getTotalPrice(), new BigDecimal(0))) {
            delAllCartItems();
            throw new CustomException(HttpStatus.NOT_FOUND, "cart has no goods");
        }
        return cartVO;
    }

    /**
     * 更改购物车单项，类似添加商品到购物车，只是讲数目设置为请求的数目
     * @param cartItemRequest
     */
    @Override
    public void updateCartItem(CartItemRequest cartItemRequest) {
        long productId = cartItemRequest.getId();

        int buyNum = cartItemRequest.getNum();

        BoundHashOperations<String, Long, String> myCart = getCart();

        if (Boolean.TRUE.equals(myCart.hasKey(productId))) {
//            商品存在
            CartItemVO cartItemVO = JSONUtil.toBean(myCart.get(productId), CartItemVO.class);
            cartItemVO.setBuyNum(buyNum);
            myCart.put(productId, JSONUtil.toJsonStr(cartItemVO));
        } else {
//            不存在
            CartItemVO cartItemVO = new CartItemVO();
            ProductVO productVO = productService.findDetail(productId);
            BeanUtil.copyProperties(productVO, cartItemVO);
            cartItemVO.setBuyNum(buyNum);
            cartItemVO.getTotalPrice();
            myCart.put(productId, JSONUtil.toJsonStr(cartItemVO));
        }
    }

    /**
     * 查询商品最新价格
     *
     * @param productIdList
     * @return
     */
    private Map<Long, ProductVO> findLatestPrice(List<Long> productIdList) {
        return productService.findProductsBathById(productIdList);
    }

    /**
     * 获取当前用户的购物车
     *
     * @return
     */
    public BoundHashOperations<String, Long, String> getCart() {
        String key = produceCartKey();
        return redisTemplate.boundHashOps(key);
    }

    /**
     * 产生购物车key
     *
     * @return
     */
    private String produceCartKey() {
        LoginUser loginUser = LoginInterceptor.threadLocal.get();
        return String.format(RedisCacheKey.CHART_KEY, loginUser.getId());
    }
}
